package cn.enjoy.tool.juc;

import lombok.Data;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @author K
 * @date 2021/7/29 上午9:23
 */
@Data
public class SynchronizedTest {

    private Integer count = 0;

    public static void main(String[] args) throws InterruptedException {
        SynchronizedTest synchronizedTest = new SynchronizedTest();
        ExecutorService executorService = Executors.newFixedThreadPool(4);
        int n = 10;
        for (int i = 0; i < 1000; i++) {
            Thread syncTask = new SyncTask(synchronizedTest, i % 2 + 1, i);
            executorService.execute(syncTask);
//            syncTask.start();
            // 等待这个线程销毁，最后能让所有线程都是顺序执行。前提是线程必须先调用start()方法
//            syncTask.join();
        }

        // 等待所有线程执行完
        executorService.shutdown();
        while (true) {
            if (executorService.isTerminated()) {
                break;
            } else {
                Thread.sleep(1000);
            }
        }

        System.out.println("Result: ");
        System.out.println(synchronizedTest.count);
    }

}

/**
 * 锁对象
 */
class SyncTask extends Thread {

    private SynchronizedTest synchronizedTest;
    private final Object lock = new Object();
    private Integer type;
    private Integer i;

    SyncTask(SynchronizedTest synchronizedTest, Integer type, Integer i) {
        this.synchronizedTest = synchronizedTest;
        this.type = type;
        this.i = i;
    }


    /**
     * synchronized 拿到锁的线程才能继续进行，否则被阻塞。可以锁三种
     * 1. 对象（一般用final来修饰）
     * 2. 类
     * 3. 方法
     */
    @Override
    public void run() {

        // 1 对象锁
        if (type == 1) {
            synchronized (lock) {
                Integer count = synchronizedTest.getCount();
                count++;
                synchronizedTest.setCount(count);

                System.out.println(String.format("1. 对象锁:\tcount:%d\ti:%d", count, i));
            }
        }

        // 2 类锁
//        if (type == 2) {
//            synchronized (SyncTask.class) {
//                Integer count = synchronizedTest.getCount();
//                count++;
//                synchronizedTest.setCount(count);
//
//                System.out.println(String.format("2. 类锁:\t\tcount:%d\ti:%d", count, i));
//            }
//        }

        // 3 方法锁
//        add();
    }

    /**
     * 锁方法，每调用这个方法都会阻塞
     * 如果是静态方法，则锁的是类
     */
    private synchronized void add() {
        Integer count = synchronizedTest.getCount();
        count++;
        synchronizedTest.setCount(count);

        System.out.println(String.format("3. 方法锁:\t\tcount:%d\ti:%d", count, i));
    }

}
